home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / dirut / bm_rm.zip / RM.C < prev    next >
C/C++ Source or Header  |  1991-07-17  |  21KB  |  473 lines

  1. /* RM - Remove files and/or directory subtrees
  2.  
  3. Copyright (C) 1989, 1990, 1991 Brian B. McGuinness
  4.                                15 Kevin Road
  5.                                Scotch Plains, NJ 07076
  6.  
  7. This program is free software; you can redistribute it and/or modify it under 
  8. the terms of the GNU General Public License as published by the Free Software 
  9. Foundation; either version 1, or (at your option) any later version.
  10.  
  11. This program is distributed in the hope that it will be useful, but WITHOUT 
  12. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  13. FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  14. details.
  15.  
  16. You should have received a copy of the GNU General Public License along with 
  17. this program; if not, write to the Free Software Foundation, Inc., 675 Mass 
  18. Ave, Cambridge, MA 02139, USA. 
  19.  
  20. This is an extended MS-DOS implementation of the *NIX RM utility.
  21.  
  22. Syntax:  RM [/AEFIRSV?] {name | @}...
  23.  
  24. /A = Detect all files, even hidden and system files, which are not normally 
  25.      detected.  If RM is used to remove files in the root directory of a 
  26.      bootable disk, especially a hard disk, /A should not be used with /F 
  27.      as there is a risk of removing the system files IBMBIO.COM (IO.SYS) and 
  28.      IBMDOS.COM (MSDOS.SYS).  This would make it impossible to boot the system 
  29.      from that disk.  
  30.  
  31. /E = Only delete matching files whose file size is zero.  Normally, we delete 
  32.      matching files regardless of their size.  This option is useful for 
  33.      disposing of empty "junk" files produced by programs or by failed 
  34.      attempts at I/O redirection.  For example, to remove ALL empty files from 
  35.      drive C:, use the command  RM /ES C:\*.*  (/S is explained below).  Note 
  36.      that empty files use up no disk space but they do use up a directory entry.
  37.  
  38. /F = Force deletion of files without asking.  Normally, we prompt the user for 
  39.      confirmation before removing read-only, hidden, or system files or before 
  40.      assuming "\*.*" at the end of a directory name (see /R below).  If the /F 
  41.      switch is used, these files are removed without any prompt being given. 
  42.  
  43. /I = Interactive mode: the user is prompted for confirmation before each file 
  44.      is removed, regardless of the file's attributes.
  45.  
  46. /R = Recursively delete entire subtrees.  Normally, when a directory name 
  47.      appears on the command line it is treated as if "\*.*" was appended to 
  48.      it.  If the /R switch is used, RM will recursively descend through any 
  49.      directory whose name is given and will remove the entire subtree that 
  50.      begins with that directory. 
  51.  
  52. /S = Delete matching files in entire subtree.  For example, entering 
  53.      RM \UTIL\*.BAK  will delete all files in the \UTIL directory which have 
  54.      the extension .BAK.  Typing  RM /S \UTIL\*.BAK  will delete all .BAK 
  55.      files in the \UTIL directory and all subdirectories of \UTIL.  Typing 
  56.      RM /S *.DOC  will remove all .DOC files in the current default directory 
  57.      and all of its subdirectories.  /S ignores directory names: e.g., if you 
  58.      have a directory called \ASM, then typing RM /S \ASM will do nothing.  To 
  59.      remove all files in \ASM and its subdirectories, type RM /S \ASM\*.*.  
  60.      This will only remove files, not directories.  Use /R to remove a whole 
  61.      subtree.
  62.  
  63. /V = Verbose: display the name of each file or directory as it is removed.
  64.  
  65. /? = Display instructions for using this program
  66.  
  67. Note: Switches become active as they are encountered on the command line.  If 
  68.       a switch is to affect a given file, it must appear before the file's 
  69.       name on the command line.
  70.  
  71. name = name of a file or directory to be removed.  Wildcards may be used.
  72.  
  73. @    = Read a list of names and/or switches from the standard input device and 
  74.        treat each of these as if it had been typed on the command line as an 
  75.        argument of RM.  More than one name and/or switch may appear on each 
  76.        line of input.  When an EOF is encountered, processing of the command 
  77.        line resumes.  
  78.  
  79.        This feature is useful when used with a file containing a lengthy list 
  80.        of names of files to be deleted.  It may also be used with any program 
  81.        which writes a list of file names to standard output: e.g. a program 
  82.        which lists all files in a given directory which have not been modified 
  83.        since a certain date. 
  84.  
  85. If the environment string VERBOSE exists and has the value ON, then RM will 
  86. act as though the /V switch is in effect even if /V is not included on the 
  87. command line.  
  88.  
  89. 1.00 August 1989    - Original version.
  90. 1.01 August 1989    - If the user presses a special key (e.g. F10) after being 
  91.                       prompted for a yes or no answer, don't echo a weird char.
  92.                       Also speed up character string output.
  93. 1.02 September 1989 - Allow the use of Esc to exit from the program.
  94. 1.03 May 1990       - Minor bug fixes and code cleanup.
  95. 1.10 July 1991      - /E switch added, messages improved.
  96.  
  97. Version 1.10          C language 
  98. ----------------------------------------------------------------------------- */
  99.  
  100. #include <stdio.h>
  101. #include <direct.h>     /* for remove() */
  102. #include <io.h>         /* for chmod() */
  103.  
  104. /* IF THE FOLLOWING KEYSTROKE IS READ IN RESPONSE TO A YES/NO PROMPT, THIS 
  105.    PROGRAM WILL IMMEDIATELY TERMINATE EXECUTION */
  106.  
  107. #define ESCAPE 27
  108.  
  109. /* DEFINE ERROR CODES */
  110.  
  111. #define SUCCESS     0
  112. #define BADSYNTAX  11
  113. #define BADSWITCH  13
  114.  
  115. /* DEFINE FILE ATTRIBUTES */
  116.  
  117. #define NORMAL     0
  118. #define READONLY   1
  119. #define HIDDEN     2
  120. #define SYSTEM     4
  121. #define DIRECTORY 16
  122. #define ARCHIVE   32
  123.  
  124. /* DEFINE FLAG VALUES FOR COMMAND LINE SWITCHES */
  125.  
  126. #define EMPTY        1          /* /E */
  127. #define FORCED       2          /* /F */
  128. #define INTERACTIVE  4          /* /I */
  129. #define RECURSIVE    8          /* /R */
  130. #define GLOBAL      16          /* /S */
  131. #define VERBOSE     32          /* /V */
  132.  
  133. /* DEFINE DATA STRUCTURE RETURNED FROM findfile() */
  134. /* Note: In the time, S = seconds / 2; in the date, Y = year - 1980 */
  135.  
  136. struct DIRINFO {
  137.   char reserved[21];            /* Undocumented (varies with DOS version) */
  138.   unsigned char attrib;         /* Attribute byte: 00ADVSHR */
  139.   unsigned short time;          /* Time file was saved: HHHHHMMMMMMSSSSS */
  140.   unsigned short date;          /* Date file was saved: YYYYYYYMMMMDDDDD */
  141.   unsigned long size;           /* File size in bytes */
  142.   char name[13];                /* File name */
  143. };
  144.  
  145. /*----------------------------------------------------------------------------*/
  146. main (int argc, char **argv) {
  147.  
  148. void delete    (char *pathname, struct DIRINFO *file, int flags);   /* Remove a file */
  149. int  delglobal (char *fname, int attributes, int flags, char *end); /* Delete file in all subdirectories */
  150. int  delmatch  (char *fname, int attributes, int flags, char *end); /* Delete matching files */
  151.  
  152. int fexpand (char *relname, char *absname);                 /* Fully qualify file name */
  153. int findfile (char *fname, int srchattr, struct DIRINFO *); /* Search directory for a file */
  154. int getkeyn();                                              /* Read keystroke and print newline */
  155. short getmode (char *fname);                                /* Get file attributes */
  156. char *nexttok (int *argc, char ***argv, int *inpflag);      /* Get next argument */
  157. void recurse (char *path, int attributes, int flags);       /* Remove a subtree */
  158. void usage (char switchar);                                 /* Display instructions */
  159.  
  160. char switchar;  /* Current MS-DOS switch character */
  161. int attrib;     /* Attributes to use to search for matching files */
  162. int flags;      /* Keeps track of command line switches */
  163. int filecnt;    /* Keeps track of how many names we've found on cmd line */
  164. int inpflag;    /* 0 = get tokens from cmd line, otherwise get them from stdin */
  165. char *token;    /* Command line token */
  166. int i;
  167.  
  168. char fullname[84];      /* Buffer for fully qualified file/directory name */
  169. char *end;              /* Location of end of f